home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / Oberon⁄F / Manuals / PSI (Macintosh) (.txt) < prev    next >
Encoding:
Oberon Document  |  1994-12-19  |  25.4 KB  |  369 lines  |  [oODC/obnF]

  1. Documents.StdDocumentDesc
  2. Documents.DocumentDesc
  3. Containers.ViewDesc
  4. Views.ViewDesc
  5. Stores.StoreDesc
  6. Documents.ModelDesc
  7. Containers.ModelDesc
  8. Models.ModelDesc
  9. Stores.ElemDesc
  10. TextViews.StdViewDesc
  11. TextViews.ViewDesc
  12. TextModels.StdModelDesc
  13. TextModels.ModelDesc
  14. TextModels.AttributesDesc
  15. Geneva
  16. TextRulers.StdRulerDesc
  17. TextRulers.RulerDesc
  18. TextRulers.StdStyleDesc
  19. TextRulers.StyleDesc
  20. TextRulers.AttributesDesc
  21. Geneva
  22. Geneva
  23. Geneva
  24. Geneva
  25. DevCommanders.StdViewDesc
  26. DevCommanders.ViewDesc
  27. MODULE SamplesMacHello; (* od, ip nov-94 *)
  28.  DevCompiler.Compile    *)
  29.  DevLinker.Link ":Samples:MacHello" +SamplesMacHello >SamplesMacHello    *)
  30. IMPORT
  31.     SYSTEM,
  32.     QD := MacQuickDraw , FN := MacFontMgr, MW := MacWindowMgr, MN := MacMenuMgr,
  33.     TE := MacTextEdit, DL := MacDialogMgr, MT := MacTypes, EV := MacEventMgr;
  34.     window: MW.WindowPtr;
  35.     wRect: QD.Rect;
  36.     string: MT.Str255;
  37. PROCEDURE InitMac;
  38. BEGIN
  39.     QD.InitGraf(QD.globals.thePort);
  40.     (* The QuickDraw Globals are proper Oberon Variables *)
  41.     FN.InitFonts;
  42.     MW.InitWindows;
  43.     MN.InitMenus;
  44.     TE.TEInit;
  45.     DL.InitDialogs(0);
  46.     QD.InitCursor;
  47. END InitMac;
  48. BEGIN
  49.     InitMac;
  50.     QD.SetRect(wRect,50,50,400,200);
  51.     window := MW.NewWindow(NIL,wRect,'',TRUE,0,SYSTEM.VAL(MW.WindowPtr,-1),FALSE,0);
  52.     QD.SetPort(window);
  53.     QD.MoveTo(30,30);
  54.     MT.SetStr255(string,'Hello World');
  55.     QD.DrawString(string)
  56.     REPEAT
  57.     UNTIL EV.Button();
  58.     MW.DisposeWindow(window);
  59. END SamplesMacHello.
  60. TextControllers.StdCtrlDesc
  61. TextControllers.ControllerDesc
  62. Containers.ControllerDesc
  63. Controllers.ControllerDesc
  64. Geneva
  65. Geneva
  66. Geneva
  67. Introduction
  68. This book describes the characteristics of the Oberon/L compiler. Moreover it gives an illustration of how to access the underlying Macintosh Toolbox from Oberon/F to write stand-alone applications or Mac OS dependent Oberon/F components.
  69. The first part would seem to be interesting to all Oberon/F programmers and should contribute to the understanding of the internal mechanisms of the runtime system.
  70. The second part is directed towards those programmers who want to make use of the Macintosh Toolbox directly and therfore sacrifice portability.
  71. In the third part a description of module SYSTEM is given.
  72. Compiler Issues
  73. Typesize, Alignment and Calling Conventions
  74. The size of Oberon basetypes is listed below. Composite types (records, arrays) are constructed out of these basetypes. Record fields and array elements whose sizes are larger than one byte are aligned to the next word (two bytes) boundary.
  75. Type    Size
  76. SHORTINT    1 byte    
  77. INTEGER    2 bytes
  78. LONGINT    4 bytes
  79. REAL    4 bytes
  80. LONGREAL    8 bytes
  81. CHAR    1 byte
  82. BOOLEAN    1 byte
  83. SET    4 bytes
  84. POINTER    4 bytes
  85. All procedure calls in Oberon/F are stack-based. The parameters are pushed according to the definition in Inside Macintosh (I-90). The space for a function result is allocated on the stack by the compiler before pushing parameters and calling the function. Used registers are saved by the caller and restored after returning from the called procedure. To prevent the stack from growing into the heap the stackpointer is checked upon every entry into a procedure, a trap is generated if the test fails.
  86. Runtime Type System
  87. All dynamically allocated records contain a hidden field, which is called the type tag. The type tag points to the type descriptor that contains all type information needed at runtime. Calls of type-bound procedures, type tests and the garbage collector all use the information which is stored in the type descriptor. The type descriptor is allocated only once for every record type in the system.
  88. Dynamically allocated arrays use a size descriptor to check the bounds of indexes. The size descriptor also contains the type tag of the elementtype. For every single dynamic array a size descriptor is needed.
  89. System Flags
  90. When interfacing to the operating system you must be able to override the default behavior of the compiler. Two different classes of system flags are used to parameterize type and procedure declarations. The extension of the Oberon
  91. 2  syntax is given below. You must import the module SYSTEM to use the extended syntax.
  92. ArrayType    =    ARRAY ["[" SysFlag "]"] [Length {"," Length}] OF Type.
  93. RecordType    =    RECORD ["[" SysFlag "]"] ["(" BaseType ")"] FieldList {; FieldList} END.
  94. PointerType    =    POINTER ["[" SysFlag "]"] TO Type.
  95. ProcedureHeading    =    PROCEDURE ["[" SysFlag "]"] [Receiver] IdentDef [FormalParameters].
  96. SysFlag    =    ConstExpression.
  97. Flag    Value    Description
  98. UNTAGGED        1    Record:     No type tag and no type descriptor are allocated.
  99. No type-bound procedures are allowed.
  100. Pointers to untagged records and extensions of untagged records inherit the attribute of being untagged.
  101.             Array:    Size descriptor is not allocated.
  102. Only one-dimensional untagged open arrays are allowed.
  103. Bounds are not checked when indexing.
  104. Pointers to untagged arrays inherit the attribute of being untagged.
  105.             Pointer:    Calling NEW is not allowed, call MacMemoryMgr.NewPtr instead.
  106. Untagged pointers are not traced by the garbage collector.
  107. You must free the heap space manually by calling MacMemoryMgr.DisposePtr.
  108. A (tagged) record may be removed by the garbage collector if referenced by untagged pointers only.
  109. HANDLE        2    Pointer:    Allowed only in pointer type. Eliminates the need to define an intermediate pointer type. Automatic double dereference when accessing fields of the associated record or array. Handles are always untagged.
  110. If the value of the intermediate pointer is required use the function procedure SYSTEM.ADR with the first record field as parameter, e.g. ptr := SYSTEM.ADR(myPicHandle.picSize).
  111. CODE        1    Procedure:    Definition of a code procedure. When calling a code procedure the byte string is directly inserted into the calling code after the parameters have been pushed. A combination with other system flags is not allowed.
  112. CALLBACK        2    Procedure:    Upon entry into a callback-procedure the registers (D0-D7, A0-A4) are saved. Used for procedures which are called by the operating system, for example procedures that are assigned to the parameter actionProc in MacControlMgr.TrackControl.
  113. NOSTKCHK        4    Procedure:    Disables the stack overflow check upon procedure entry. Necessary for procedures called at interrupt time, e.g. handler in VBLTask (MacVBLMgr.VBLTask.vblAddr).
  114. The values of the system flags should be defined in the CONST section of the module. The system flags CALLBACK and NOSTKCHK can be combined by adding their values. A typical definition of a VBLTaskHandler is therefore: PROCEDURE [CALLBACK + NOSTKCHK] Handle;
  115. Implementation Restrictions
  116. max. codesize:    8 MB per module.
  117. max. global VAR size:    unlimited
  118. max. local VAR size:    unlimited
  119. max. CONST size:    unlimited
  120. max. imported modules:    127 per module (direct or indirect)
  121. max. exported objects:    unlimited (except types)
  122. max. exported types:    1024 per module
  123. max. height of type hierachy:    16 (including basetype)
  124. max. loaded modules:    unlimited
  125. Interfacing the Macintosh Toolbox
  126. Interface Modules
  127. The Macintosh Toolbox is accessed through a set of interface modules, together they form the subsystem Mac. Interface modules are common Oberon modules, but importing a interface module makes your code Mac OS dependent. Every interface module provides access to one Macintosh Toolbox Manager. All calls to routines in the interface modules are stack-based, the interface modules provide the glue code wherever it is necessary.
  128. Type extension is used for defining hierarchical types. This makes access to record fields more natural, first because there is no need for a distinction between Ptr and Peek. Peeks are not defined in the interface modules as they would never be used. Second you can access the fields of basetypes directly without having to specify the record first.
  129. An example: 
  130.     DialogPtr* = POINTER TO DialogRecord;
  131.     DialogRecord* = RECORD (MacWindowMgr.WindowRecord)
  132.         items*: MacTypes.Handle;
  133.         textH*: MacTextEdit.TEHandle;
  134.         editField*: INTEGER;
  135.         editOpen: INTEGER;    (* used internally, therefore not exported *)
  136.         aDefItem*: INTEGER
  137.     END;
  138. VAR dlg: DialogPtr;
  139.     rect := dlg.portRect;    (* portRect is a field of GrafPort *)
  140.     items :=  dlg.items;    (* in Pascal this would be: DialogPeek(dlg).items *)
  141.     MacWindowMgr.HideWindow(dlg); (* dlg is an extension of WindowPtr *)
  142. Common types such as Str255 and Handle are defined in the module MacTypes. The interface module MacTypes also exports procedures to convert zero-terminated strings (Oberon, C) into pascal-type strings with a leading length byte.
  143. Composing New Interface Modules
  144. If you want to add interface modules which are not part of this distribution, you can create them yourself. Keep in mind that all operating system records have to be declared as untagged.
  145. An example for a routine which requires glue code:
  146.     Ptr = POINTER [UNTAGGED] TO Data;
  147.     Data = RECORD [UNTAGGED] END;
  148. PROCEDURE [CODE] newPtr 0A1H, 01EH;    (* A-Trap definition *)
  149. PROCEDURE NewPtr* (byteCount: Size): Ptr;    (* Routine with glue *)
  150.     VAR p: Ptr;
  151. BEGIN
  152.     SYSTEM.PUTREG(D0, byteCount);
  153.     newPtr;
  154.     SYSTEM.GETREG(D0, err);
  155.     SYSTEM.GETREG(A0, p);
  156.     RETURN p
  157. END NewPtr;
  158. Writing Macintosh Applications Using Oberon/F
  159. After a short introduction to Macintosh programming in Oberon/F through several examples we describe the command interface of the Linker and give an overview what to bear in mind when using garbage collection and NEW in your stand-alone applications.
  160. The first example displays the string "Hello World" in a window and waits until the mouse button is pressed. To reduce the typing effort and the readability of the program we used aliasing when importing the interface modules. Notice that the QuickDraw globals used during initialization are common global  variables of the interface module MacQuickDraw. To compile and link the application execute the two commands in the module header. The applicationfile is generated in the Samples folder.
  161. The following example uses the File Manager and QuickDraw to a greater extent. When run, the application opens a PICT-file and displays the picture in a window which occupies the main screen. Use Compile
  162. Selection to compile the module below.
  163. MODULE SamplesMacPICTView;    (* od, ip nov-94 *)
  164.  DevLinker.Link ":Samples:MacPICTView" +SamplesMacPICTView >SamplesMacPICTView    *)
  165. (*    In this example error checking is reduced to a minimum in favor of readability!    *)
  166. IMPORT
  167.     SYSTEM,
  168.     QD := MacQuickDraw , FS := MacFileMgr, FN := MacFontMgr, MW := MacWindowMgr,
  169.     MN := MacMenuMgr, TE := MacTextEdit, DL := MacDialogMgr, MT := MacTypes,
  170.     EV := MacEventMgr, ME := MacMemoryMgr;
  171. PROCEDURE InitMac;
  172. BEGIN
  173.     QD.InitGraf(QD.globals.thePort);
  174.     FN.InitFonts;
  175.     MW.InitWindows;
  176.     MN.InitMenus;
  177.     TE.TEInit;
  178.     DL.InitDialogs(0);
  179.     QD.InitCursor;
  180. END InitMac;
  181. PROCEDURE OpenPict;
  182.     myTypes: FS.SFTypeList;
  183.     myReply: FS.StandardFileReply;
  184.     myRef: INTEGER;
  185.     fsize: LONGINT;
  186.     myPic: QD.PicHandle;
  187.     err: INTEGER;
  188.     myWindow: MW.WindowPtr;
  189. BEGIN
  190.     myTypes[0]:=50494354H; (* PICT *)
  191.     FS.StandardGetFile(NIL, 1, myTypes, myReply);
  192.     IF myReply.sfGood THEN
  193.         err:=FS.FSpOpenDF(myReply.sfFile, 0, myRef);
  194.         err:=FS.GetEOF(myRef, fsize);
  195.         err:=FS.SetFPos(myRef, 1, 512);
  196.         DEC(fsize, 512);    (* strip PICT-header *)
  197.         myPic := SYSTEM.VAL(QD.PicHandle, ME.NewHandle(fsize));
  198.         IF myPic#NIL THEN
  199.             err:=FS.FSRead(myRef, fsize, SYSTEM.VAL(MT.Ptr, SYSTEM.ADR(myPic.picSize)));
  200.             err:=FS.FSClose(myRef);
  201.             myWindow:=MW.NewWindow(NIL, QD.globals.screenBits.bounds, '', TRUE, 1,
  202.                     SYSTEM.VAL(MW.WindowPtr, -1), FALSE, 0);
  203.             QD.SetPort(myWindow);
  204.             QD.OffsetRect(myPic.picFrame, -myPic.picFrame.left, -myPic.picFrame.top);
  205.             QD.DrawPicture(myPic, myPic.picFrame);
  206.             REPEAT UNTIL EV.Button();
  207.             MW.DisposeWindow(myWindow)
  208.         END
  209. END OpenPict;
  210. BEGIN
  211.     InitMac;
  212.     OpenPict;
  213. END SamplesMacPICTView.
  214. A common pitfall when porting Pascal programs is that the CASE-statement in Oberon/L generates a runtime error if none of the case labels holds and no ELSE-branch is available. As a consequence you must add an empty ELSE-branch to your message handlers.
  215. The Linker
  216. Stand-alone applications are linked using DevLinker. DevLinker copies the relevant information out of the code files into resources of type "oOBF". Additional boot information is stored in resources of type "bOBF". A "CODE"-resource containing the boot loader is also generated. Resources with other types are left untouched, you don't need to specify a seperate resource file from which to copy all resources.
  217. The textual interface to DevLinker is as follows:
  218.  DevLinker.Link "application" + module0 module1 ... modulei  > mainmodule
  219. application:    Filename of the application. A new file is generated if no file with the specified name exists otherwise the old file is reused. Existing resources of the types "CODE", "oOBF" and "bOBF" are removed before linking takes place. 
  220. module0..i:    Modules linked into the application. Imported modules are linked automatically, you need to list only the top modules. For instance, all necessary interface modules are linked.
  221. mainmodule:    At startup the bodies of the main module and all underlying modules are executed. Usually the toplevel module is specified, which should also appear as the last in the list of linked modules. Modules on the same level are initialized in the order in which they appear in the link list or import list of the importing module. The mainmodule should always be the last in the modulelist with one exception: the Kernel is always first in the module list (see next chapter).
  222. Using NEW and Garbage Collection in Your Applications
  223. If you are calling NEW in your application and thereby implicitly use the garbage collector, you must link the Kernel into the application. The NEW-procedure is implemented in the kernel, the compiler just generates the code to call this procedure. So every module using NEW has a hidden import of the kernel. The kernel must be the first module in the list of linked modules and should be specified as the main module. During initialization, the kernel seizes control from the boot loader and traverses the list of loaded modules which has been generated by the boot loader and calls subsequently all module bodies. Don't call MacOSUtils.ExitToShell directly when "importing" the kernel, call Kernel.Quit with parameter zero instead to assure that occupied system resources get properly released before the application is terminated.
  224. Programs don't need to call the garbage collector explicitly. If the NEW-procedure cannot satisfy a request for heap space it calls the garbage collector internally before allocating a new heap block from the Macintosh Memory Manager. The garbage collector marks pointers in stackframes and is able to run anytime except at interrupt-time. As a consequence calling NEW is not allowed during interrupt handling.
  225. Accessing the Macintosh Toolbox when Programming Components in Oberon/F
  226. As an example of a view which depends on the underlying operating system we provide stripped-down source code of the module HostPictures:
  227. MODULE SamplesHostPictures;
  228.     IMPORT
  229.         SYSTEM, MacTypes, MemoryMgr := MacMemoryMgr, QuickDraw := MacQuickDraw,
  230.         Files, Ports, Stores, Models, Views, HostPorts;
  231.     CONST
  232.         clip = 0X; fit = 1X; approximate = 2X;    (* modes *)
  233.         minVersion = 0; maxVersion = 0;
  234.         macPict = 0;
  235.     TYPE
  236.         Model = POINTER TO ModelDesc;
  237.         ModelDesc = RECORD
  238.             file: Files.File;
  239.             pos, len: LONGINT;
  240.             picture: QuickDraw.PicHandle
  241.         END;
  242.         StdView = POINTER TO StdViewDesc;
  243.         StdViewDesc = RECORD (Views.ViewDesc)
  244.             model: Model;
  245.             unit: LONGINT;
  246.             w, h: LONGINT;
  247.             mode: CHAR
  248.         END;
  249.     PROCEDURE NewModel (pic: QuickDraw.PicHandle): Model;
  250.         VAR m: Model;
  251.     BEGIN
  252.         ASSERT(pic # NIL, 20);
  253.         NEW(m); m.file := NIL;
  254.         m.picture := pic; m.len := pic.picSize + 10;
  255.         RETURN m
  256.     END NewModel;
  257.     PROCEDURE Evaluate (v: StdView);
  258.         VAR hdl: MacTypes.Handle; len, adr: LONGINT; rd: Files.Reader; ch: CHAR;
  259.     BEGIN
  260.         len := v.model.len; ASSERT(len > 0, 21);
  261.         hdl := MemoryMgr.NewHandle(len); ASSERT(hdl # NIL, 22); MemoryMgr.HLock(hdl);
  262.         v.model.picture := SYSTEM.VAL(QuickDraw.PicHandle, hdl);
  263.         ASSERT(v.model.file # NIL, 23);
  264.         rd := v.model.file.NewReader(NIL); ASSERT(rd # NIL, 24);
  265.         rd.SetPos(v.model.pos);
  266.         adr := SYSTEM.ADR(v.model.picture^);
  267.         WHILE len # 0 DO rd.ReadByte(ch); SYSTEM.PUT(adr, ch); INC(adr); DEC(len) END;
  268.         ASSERT(v.model.len = v.model.picture.picSize + 10, 28)
  269.     END Evaluate;
  270.     (* View *)
  271.     PROCEDURE (v: StdView) Internalize (VAR rd: Stores.Reader);
  272.         VAR m: Model; thisVersion, type: SHORTINT;
  273.     BEGIN
  274.         v.Internalize^(rd);
  275.         IF rd.cancelled THEN RETURN END;
  276.         rd.ReadVersion(minVersion, maxVersion, thisVersion);
  277.         IF rd.cancelled THEN RETURN END;
  278.         rd.ReadSInt(type);
  279.         IF type # macPict THEN rd.TurnIntoAlien(Stores.alienComponent); RETURN END;
  280.         rd.ReadLInt(v.unit);
  281.         rd.ReadLInt(v.w);
  282.         rd.ReadLInt(v.h);
  283.         rd.ReadChar(v.mode);
  284.         NEW(m); m.file := rd.rider.Base();
  285.         rd.ReadLInt(m.len);
  286.         m.pos := rd.Pos();
  287.         m.picture := NIL;    (* lazy allocation of picture *)
  288.         v.model := m;
  289.         rd.SetPos(m.pos + m.len)
  290.     END Internalize;
  291.     PROCEDURE (v: StdView) Externalize (VAR wr: Stores.Writer);
  292.         VAR len, adr: LONGINT; r: Files.Reader; ch: CHAR;
  293.     BEGIN
  294.         v.Externalize^(wr);
  295.         wr.WriteVersion(maxVersion);
  296.         wr.WriteSInt(macPict);
  297.         wr.WriteLInt(v.unit);
  298.         wr.WriteLInt(v.w);
  299.         wr.WriteLInt(v.h);
  300.         wr.WriteChar(v.mode);
  301.         len := v.model.len;
  302.         wr.WriteLInt(len);
  303.         IF v.model.picture = NIL THEN
  304.             r := v.model.file.NewReader(NIL); r.SetPos(v.model.pos);
  305.             WHILE len # 0 DO r.ReadByte(ch); wr.WriteChar(ch); DEC(len) END
  306.         ELSE
  307.             adr := SYSTEM.ADR(v.model.picture^);
  308.             WHILE len # 0 DO SYSTEM.GET(adr, ch); INC(adr); wr.WriteChar(ch); DEC(len) END
  309.         END
  310.     END Externalize;
  311.     PROCEDURE (v: StdView) ThisModel (): Models.Model;
  312.     BEGIN
  313.         RETURN NIL
  314.     END ThisModel;
  315.     PROCEDURE (v: StdView) CopyModelFrom (source: Views.View; shallow: BOOLEAN);
  316.     BEGIN
  317.         v.model := source(StdView).model    (* model is immutable *)
  318.     END CopyModelFrom;
  319.     PROCEDURE (v: StdView) Restore (f: Views.Frame; l, t, r, b: LONGINT);
  320.         VAR rd: HostPorts.Rider; u, w, h: LONGINT; dst, c1: QuickDraw.Rect; pinX, pinY: INTEGER;
  321.     BEGIN
  322.         ASSERT(v.model # NIL, 20);
  323.         IF v.model.picture = NIL THEN Evaluate(v) END;
  324.         v.context.GetSize(w, h);
  325.         HostPorts.ResetPort(f.rider(HostPorts.Rider));
  326.         u := f.unit;
  327.         rd := f.rider(HostPorts.Rider);
  328.         c1 := rd.c; pinX := rd.pinX; pinY := rd.pinY;
  329.         INC(c1.left, pinX); INC(c1.top, pinY);
  330.         INC(c1.right, pinX); INC(c1.bottom, pinY);
  331.         QuickDraw.ClipRect(c1); QuickDraw.SetOrigin(pinX, pinY);
  332.         dst.left := SHORT(f.gx DIV u + pinX);
  333.         dst.top := SHORT(f.gy DIV u + pinY);
  334.         dst.right := SHORT((f.gx + w) DIV u + pinX);
  335.         dst.bottom := SHORT((f.gy + h) DIV u + pinY);
  336.         QuickDraw.DrawPicture(v.model.picture, dst);
  337.         QuickDraw.SetOrigin(0, 0)
  338.     END Restore;
  339. END SamplesHostPictures.
  340. Module SYSTEM
  341. Module SYSTEM contains certain procedures that are necessary to implement low-level operations. It is strongly recommended to restrict its use to specific low-level modules, as such modules are inherently non-portable. SYSTEM is not considered as part of Oberon/L proper.
  342. The procedures contained in module SYSTEM are listed in the following table. v stands for a variable. x, y, and n stands for expressions. T stands for a type. P stands for a procedure. M[a] stands for memory value at address a.
  343. Function procedures
  344.     Name    Argument types    Result type    Description
  345.     ADR(v)    any    LONGINT    address of variable v
  346.     ADR(P)    P:PROCEDURE    LONGINT    address of Procedure P
  347.     ADR(T)    T: a record type    LONGINT    address of Descriptor of T
  348.     LSH(x, n)    x, n: integer type    type of x    logical shift (n > 0: left, n < 0: right)
  349.     ROT(x, n)    x, n: integer type    type of x    rotation (n > 0: left, n < 0: right)
  350.     VAL(T, x)    T, x: any type    T    x interpreted as of type T
  351. Proper procedures
  352.     Name    Argument types        Description
  353.     GET(a, v)    a: LONGINT; v: any basic type,    v := M[a]
  354.         pointer type, procedure type
  355.     PUT(a, x)    a: LONGINT; x: any basic type,    M[a] := x
  356.         pointer type, procedure type
  357.     GETREG(n, v)    n: integer constant, v: any basic type,    v := Register n
  358.         pointer type, procedure type
  359.     PUTREG(n, x)    n: integer constant, x: any basic type,    Register n := x
  360.         pointer type, procedure type
  361.     MOVE(a0, a1, n)    a0, a1: LONGINT; n: integer type    M[a1..a1+n-1] := M[a0..a0+n-1]
  362. The register numbers for PUTREG and GETREG are:
  363. D0..D7: 0..7; A0..A7: 8..15; F0..F7: 16..24
  364. warning
  365. PUT, PUTREG, and MOVE may crash Oberon/F and/or the Macintosh when not used properly.
  366. Never use VAL to assign a value to an Oberon/F pointer. Doing this would corrupt the garbage collector, with fatal consequences.
  367. Geneva
  368. Documents.ControllerDesc
  369.